/*
 * 函数防抖 immediate true 表立即执行，false 表非立即执行
 * */
export function debounce(func, wait, immediate) {
	let timeout;
	return function () {
		// 保留调用时的 this 上下文
		const context = this;
		// 保留调用时传入的参数
		const args = arguments;
		// 每次事件被触发时，都去清除之前的旧定时器
		if (timeout) clearTimeout(timeout);
		if (immediate) {
			let callNow = !timeout;
			timeout = setTimeout(() => {
				timeout = null;
			}, wait);
			if (callNow) func.apply(context, args);
		} else {
			timeout = setTimeout(function () {
				func.apply(context, args);
			}, wait);
		}
	};
}
export function debounce2(func, wait, immediate) {
	let timeout, args, context, timestamp, result;

	const later = function () {
		// 据上一次触发时间间隔
		const last = +new Date() - timestamp;

		// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
		if (last < wait && last > 0) {
			timeout = setTimeout(later, wait - last);
		} else {
			timeout = null;
			// 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
			if (!immediate) {
				result = func.apply(context, args);
				if (!timeout) context = args = null;
			}
		}
	};

	return function (...args) {
		context = this;
		timestamp = +new Date();
		const callNow = immediate && !timeout;
		// 如果延时不存在，重新设定延时
		if (!timeout) timeout = setTimeout(later, wait);
		if (callNow) {
			result = func.apply(context, args);
			context = args = null;
		}

		return result;
	};
}

/*
 * 函数节流
 * */
// fn 是我们需要包装的事件回调, delay 是时间间隔的阈值
export function throttle(fn, delay) {
	// last 为上一次触发回调的时间
	let last = 0;

	// 将 throttle 处理结果当作函数返回
	return function () {
		// 保留调用时的 this 上下文
		const context = this;
		// 保留调用时传入的参数
		const args = arguments;
		// 记录本次触发回调的时间
		const now = +new Date();

		// 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
		if (now - last >= delay) {
			// 如果时间间隔大于我们设定的时间间隔阈值，则执行回调
			last = now;
			fn.apply(context, args);
		}
	};
}
